{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Floats - Internal Representation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``float`` class can be used to represent real numbers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on class float in module builtins:\n",
      "\n",
      "class float(object)\n",
      " |  float(x) -> floating point number\n",
      " |  \n",
      " |  Convert a string or number to a floating point number, if possible.\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __abs__(self, /)\n",
      " |      abs(self)\n",
      " |  \n",
      " |  __add__(self, value, /)\n",
      " |      Return self+value.\n",
      " |  \n",
      " |  __bool__(self, /)\n",
      " |      self != 0\n",
      " |  \n",
      " |  __divmod__(self, value, /)\n",
      " |      Return divmod(self, value).\n",
      " |  \n",
      " |  __eq__(self, value, /)\n",
      " |      Return self==value.\n",
      " |  \n",
      " |  __float__(self, /)\n",
      " |      float(self)\n",
      " |  \n",
      " |  __floordiv__(self, value, /)\n",
      " |      Return self//value.\n",
      " |  \n",
      " |  __format__(...)\n",
      " |      float.__format__(format_spec) -> string\n",
      " |      \n",
      " |      Formats the float according to format_spec.\n",
      " |  \n",
      " |  __ge__(self, value, /)\n",
      " |      Return self>=value.\n",
      " |  \n",
      " |  __getattribute__(self, name, /)\n",
      " |      Return getattr(self, name).\n",
      " |  \n",
      " |  __getformat__(...) from builtins.type\n",
      " |      float.__getformat__(typestr) -> string\n",
      " |      \n",
      " |      You probably don't want to use this function.  It exists mainly to be\n",
      " |      used in Python's test suite.\n",
      " |      \n",
      " |      typestr must be 'double' or 'float'.  This function returns whichever of\n",
      " |      'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n",
      " |      format of floating point numbers used by the C type named by typestr.\n",
      " |  \n",
      " |  __getnewargs__(...)\n",
      " |  \n",
      " |  __gt__(self, value, /)\n",
      " |      Return self>value.\n",
      " |  \n",
      " |  __hash__(self, /)\n",
      " |      Return hash(self).\n",
      " |  \n",
      " |  __int__(self, /)\n",
      " |      int(self)\n",
      " |  \n",
      " |  __le__(self, value, /)\n",
      " |      Return self<=value.\n",
      " |  \n",
      " |  __lt__(self, value, /)\n",
      " |      Return self<value.\n",
      " |  \n",
      " |  __mod__(self, value, /)\n",
      " |      Return self%value.\n",
      " |  \n",
      " |  __mul__(self, value, /)\n",
      " |      Return self*value.\n",
      " |  \n",
      " |  __ne__(self, value, /)\n",
      " |      Return self!=value.\n",
      " |  \n",
      " |  __neg__(self, /)\n",
      " |      -self\n",
      " |  \n",
      " |  __new__(*args, **kwargs) from builtins.type\n",
      " |      Create and return a new object.  See help(type) for accurate signature.\n",
      " |  \n",
      " |  __pos__(self, /)\n",
      " |      +self\n",
      " |  \n",
      " |  __pow__(self, value, mod=None, /)\n",
      " |      Return pow(self, value, mod).\n",
      " |  \n",
      " |  __radd__(self, value, /)\n",
      " |      Return value+self.\n",
      " |  \n",
      " |  __rdivmod__(self, value, /)\n",
      " |      Return divmod(value, self).\n",
      " |  \n",
      " |  __repr__(self, /)\n",
      " |      Return repr(self).\n",
      " |  \n",
      " |  __rfloordiv__(self, value, /)\n",
      " |      Return value//self.\n",
      " |  \n",
      " |  __rmod__(self, value, /)\n",
      " |      Return value%self.\n",
      " |  \n",
      " |  __rmul__(self, value, /)\n",
      " |      Return value*self.\n",
      " |  \n",
      " |  __round__(...)\n",
      " |      Return the Integral closest to x, rounding half toward even.\n",
      " |      When an argument is passed, work like built-in round(x, ndigits).\n",
      " |  \n",
      " |  __rpow__(self, value, mod=None, /)\n",
      " |      Return pow(value, self, mod).\n",
      " |  \n",
      " |  __rsub__(self, value, /)\n",
      " |      Return value-self.\n",
      " |  \n",
      " |  __rtruediv__(self, value, /)\n",
      " |      Return value/self.\n",
      " |  \n",
      " |  __setformat__(...) from builtins.type\n",
      " |      float.__setformat__(typestr, fmt) -> None\n",
      " |      \n",
      " |      You probably don't want to use this function.  It exists mainly to be\n",
      " |      used in Python's test suite.\n",
      " |      \n",
      " |      typestr must be 'double' or 'float'.  fmt must be one of 'unknown',\n",
      " |      'IEEE, big-endian' or 'IEEE, little-endian', and in addition can only be\n",
      " |      one of the latter two if it appears to match the underlying C reality.\n",
      " |      \n",
      " |      Override the automatic determination of C-level floating point type.\n",
      " |      This affects how floats are converted to and from binary strings.\n",
      " |  \n",
      " |  __str__(self, /)\n",
      " |      Return str(self).\n",
      " |  \n",
      " |  __sub__(self, value, /)\n",
      " |      Return self-value.\n",
      " |  \n",
      " |  __truediv__(self, value, /)\n",
      " |      Return self/value.\n",
      " |  \n",
      " |  __trunc__(...)\n",
      " |      Return the Integral closest to x between 0 and x.\n",
      " |  \n",
      " |  as_integer_ratio(...)\n",
      " |      float.as_integer_ratio() -> (int, int)\n",
      " |      \n",
      " |      Return a pair of integers, whose ratio is exactly equal to the original\n",
      " |      float and with a positive denominator.\n",
      " |      Raise OverflowError on infinities and a ValueError on NaNs.\n",
      " |      \n",
      " |      >>> (10.0).as_integer_ratio()\n",
      " |      (10, 1)\n",
      " |      >>> (0.0).as_integer_ratio()\n",
      " |      (0, 1)\n",
      " |      >>> (-.25).as_integer_ratio()\n",
      " |      (-1, 4)\n",
      " |  \n",
      " |  conjugate(...)\n",
      " |      Return self, the complex conjugate of any float.\n",
      " |  \n",
      " |  fromhex(...) from builtins.type\n",
      " |      float.fromhex(string) -> float\n",
      " |      \n",
      " |      Create a floating-point number from a hexadecimal string.\n",
      " |      >>> float.fromhex('0x1.ffffp10')\n",
      " |      2047.984375\n",
      " |      >>> float.fromhex('-0x1p-1074')\n",
      " |      -5e-324\n",
      " |  \n",
      " |  hex(...)\n",
      " |      float.hex() -> string\n",
      " |      \n",
      " |      Return a hexadecimal representation of a floating-point number.\n",
      " |      >>> (-0.1).hex()\n",
      " |      '-0x1.999999999999ap-4'\n",
      " |      >>> 3.14159.hex()\n",
      " |      '0x1.921f9f01b866ep+1'\n",
      " |  \n",
      " |  is_integer(...)\n",
      " |      Return True if the float is an integer.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  imag\n",
      " |      the imaginary part of a complex number\n",
      " |  \n",
      " |  real\n",
      " |      the real part of a complex number\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(float)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The ``float`` class has a single constructor, which can take a number or a string and will attempt to convert it to a float."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10.0"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.14"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float(3.14)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.1"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float('0.1')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, strings that represent fractions cannot be converted to floats, unlike the Fraction class we saw earlier."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "could not convert string to float: '22/7'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-5-32cff4369993>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mfloat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'22/7'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m: could not convert string to float: '22/7'"
     ]
    }
   ],
   "source": [
    "float('22/7')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you really want to get a float from a string such as ``'22/7'``, you could first create a ``Fraction``, then create a ``float`` from that:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from fractions import Fraction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "float(Fraction('22/7'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Floats do not always have an exact representation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although this looks like ``0.1`` exactly, we need to reveal more digits after the decimal point to see what's going on:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "format(0.1, '.25f')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, certain numbers can be represented exactly in a binary fraction expansion:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "format(0.125, '.25f')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is because 0.125 is precisely 1/8, or 1/(2^3)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
